import axios from 'axios';
import { Message, Loading } from 'element-ui';
import debounce from 'lodash/debounce';
// import tokenHandler from '@utils/tokenHandler.js';

class AxiosHandler {
    constructor() {
        //构造实例
        if (!AxiosHandler.singletonInstance) {
            this._instance = null; //axios实例对象
            // axios默认配置参数
            this._defaultConfig = {
                baseURL: '', //axios默认请求地址
                timeout: 10000, //超时时间10秒
                withCredentials: false // 允许携带cookie
            };
            this._loading = null; //loading对象
            this._needLoadingCount = 0; //当前正在请求的数量

            //将this挂载到AxiosHandler类的singletonInstance属性上
            AxiosHandler.singletonInstance = this;
            // axios初始化
            this.initRequest();
        }
        return AxiosHandler.singletonInstance;
    }
    mergeConfig(options) {
        this._defaultConfig = Object.assign(this._defaultConfig, options);
    }
    updateBaseUrl(baseUrl) {
        this._instance.defaults.baseURL = baseUrl;
    }
    initRequest() {
        // 创建axios实例
        this._instance = axios.create(this._defaultConfig);

        // 添加请求拦截器
        this._instance.interceptors.request.use(
            config => {
                // 获取token
                // const token = tokenHandler.getToken();
                // if (token) {
                //     config.headers.token = token;
                // }
                //判断当前请求是否设置了不显示Loading
                if (config.headers.showLoading !== false) {
                    this.showLoading(config.headers.loadingTarget);
                }
                return config;
            },
            error => {
                //判断当前请求是否设置了不显示Loading
                if (error.config.headers.showLoading !== false) {
                    this.hideLoading();
                }
                Message.error('Time Out');
                return Promise.resolve(error);
            }
        );

        // 添加响应拦截器
        this._instance.interceptors.response.use(
            response => {
                //判断当前请求是否设置了不显示Loading（不显示自然无需隐藏）
                if (response.config.headers.showLoading !== false) {
                    this.hideLoading();
                }
                return response;
            },
            error => {
                //判断当前请求是否设置了不显示Loading（不显示自然无需隐藏）
                if (error.config.headers.showLoading !== false) {
                    this.hideLoading();
                }
                if (error.response && error.response.data && error.response.data.message) {
                    const jsonObj = JSON.parse(error.response.data.message);
                    Message.error(jsonObj.message);
                } else {
                    Message.error(error.message);
                }
                return Promise.reject(error);
            }
        );
    }
    showLoading(target) {
        // 这个判断很重要，因为关闭时加了抖动，此时loading对象可能还存在，但needLoadingCount已经变成0.避免这种情况下会重新创建个loading
        if (this._needLoadingCount === 0 && !this._loading) {
            this._loading = Loading.service({
                lock: true,
                text: 'Loading...',
                background: 'rgba(0, 0, 0, 0.8)',
                target: target || 'body'
            });
        }
        this._needLoadingCount++;
    }
    hideLoading() {
        this._needLoadingCount--;
        this._needLoadingCount = Math.max(this._needLoadingCount, 0);
        if (this._needLoadingCount === 0) {
            //关闭loading
            this.toHideLoading();
        }
    }
    toHideLoading = debounce(function () {
        // eslint-disable-next-line no-invalid-this
        if (this._loading) {
            // eslint-disable-next-line no-invalid-this
            this._loading.close();
            // eslint-disable-next-line no-invalid-this
            this._loading = null;
        }
    }, 300);
    get(url, paramData = {}, config = {}) {
        try {
            return new Promise((resolve, reject) => {
                this._instance.get(url, { params: paramData }, config).then(
                    response => {
                        resolve(response.data);
                    },
                    err => {
                        reject(err);
                    }
                );
            });
        } catch (err) {
            console.error(err);
        }
    }
    post(url, paramData, config = {}) {
        try {
            return new Promise((resolve, reject) => {
                this._instance.post(url, paramData, config).then(
                    response => {
                        resolve(response.data);
                    },
                    err => {
                        reject(err);
                    }
                );
            });
        } catch (err) {
            console.error(err);
        }
    }
    put(url, paramData, config = {}) {
        try {
            return new Promise((resolve, reject) => {
                this._instance.put(url, paramData, config).then(
                    response => {
                        resolve(response.data);
                    },
                    err => {
                        reject(err);
                    }
                );
            });
        } catch (err) {
            console.error(err);
        }
    }
    del(url, paramData = {}, config = {}) {
        try {
            return new Promise((resolve, reject) => {
                this._instance.delete(url, { params: paramData }, config).then(
                    response => {
                        resolve(response.data);
                    },
                    err => {
                        reject(err);
                    }
                );
            });
        } catch (err) {
            console.error(err);
        }
    }
}

export default new AxiosHandler();
